VPC Peeringで他AWSアカウントのS3にファイルをアップロードしよう
こんにちはクラスメソッドのスジェです。
この前、自分持ちではないS3にファイルをアップロードする方法を調べたことがあります。
その中でVPC Peeringと他アカウントのVPC endpointを通じて、AWSネットワークだけでS3にファイルをアップロードする方法があるので書いてみます。
(インターネットを経由しないで他アカウントのS3バケットにファイルをアップロードすることだけが目的であれば、VPC Gateway Endpointだけでも問題ありません。)
構成
VPC peeringが設定されていない既存の構成は、このようにインターネットを通じてS3にファイルをアップロードしています。
VPC peeringを設定するとこのようにAWSネットワークを通じてファイルをアップロードします。
やってみよう
VPC endpointとは?
VPC エンドポイントを使用すると、Virtual Private Cloud (VPC) とサポートされているサービスの間の接続が有効になります。インターネットゲートウェイ、NAT デバイス、VPN 接続、および AWS Direct Connect 接続は必要ありません。したがって、VPC はパブリックインターネットに公開されません。 - 公式ドキュメント
パブリックインターネットに公開されずAWSネットワークで通信できるようにするサービスです。
インターフェイスエンドポイント(AWS Privatelink)とゲートウェイエンドポイントタイプがあります。
本記事ではインターフェイスエンドポイントを利用します。
また、エンドポイント自体のコストも発生します。
詳細な内容は公式ドキュメントを参考してください。
前提
ピアリングを作成してファイルをアップロードするアカウントをアカウントA
S3を持っているアカウントをアカウントB とします。
手順
本記事ではVPC peeringの設定から始めます。
- ピアリング設定
- エンドポイント設定
- S3作成、ポリシー設定
- EC2からファイルアップロード
ピアリング設定
アカウントA からアカウントB にピアリングを作成します。
VPCコンソールの[ピアリング接続]で接続を作成します。
下記のような画面でピアリングを接続するアカウント A のVPCを選びます。
続いてアカウントB のID、VPC ID を記入します。
作成したらアカウントB が接続を許可するまでステータスが承諾の保留中(Pending acceptance) となります。
アカウントB にログインしてVPCコンソールのピアリング接続で承諾の保留中の接続をクリックし[アクション - リクエストの承諾]で接続を完了します。
少し待機したらステータスが変わります。
続いてピアリング接続を作成したVPCのプライベートルートテーブルにピアリング接続のルートを追加します。
送信先(Destination)にはアカウントB のVPCのcidrを記入します。
エンドポイント設定
アカウントB でインターフェイスエンドポイントを作成します。
その前にエンドポイントに適用するセキュリティグループを作成します。
アカウントA のピアリングされたVPCのcidr からの通信を許可するようにインバウンドを設定します。
その後VPCコンソールの[エンドポイント]でエンドポイントを作成します。
s3サービスのinterface タイプ、対象のVPCと作成したセキュリティグループを指定します。必要によってポリシーも設定します。
S3作成
アカウントBでS3を作成してからポリシーを更新します。
既に利用していたS3をそのまま利用する場合はポリシーだけ更新します。
本記事ではsujae-peering-test-1 というバケットを作成し、次の通りにポリシーを設定しました。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "DelegateS3Access", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::{アカウントA のID}:role/{アカウントA のEC2に設定されるロール名}" }, "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::sujae-peering-test-1", "arn:aws:s3:::sujae-peering-test-1/*" ] } ] }
EC2 からファイルアップロード
最後にEC2 からファイルをアップロードしてみます。
まずS3 にアップロードできるようにロールをEC2 に指定します。
アカウントB でS3 ポリシーに設定した{アカウントA のEC2に設定されるロール名}にロール名を設定します。
続いて内部EC2(private subnetのEC2)に接続します。先ずはエンドポイントを指定しなくてS3 にファイルをアップロードすると次のようなコマンドでできます。
aws s3 cp test.txt s3://sujae-peering-test-1/test.txt
既存構成でNAT gatewayが接続されているため、問題なくアップロードが可能でした。ではルートテーブルでNAT gatewayのルートを削除します。
続いてエンドポイント経由でファイルをアップロードしてみます。そのためにエンドポイントのURLが必要になりますがここで確認できます。
下記のコマンドにURL を代入して実行してみます。
もしエラーが発生するとピアリング接続、バケットポリシー、エンドポイントURLなどを確認してみます。
# aws s3 --endpoint-url https://bucket.{エンドポイントのURL} ls s3://{バケット名} aws s3 --endpoint-url https://bucket.vpce-0700000000000-1234567.s3.ap-northeast-1.vpce.amazonaws.com ls s3://sujae-peering-test-1
アップロードした test.txt が確認できたら、続いてアップロードをしてみます。
# aws s3 --endpoint-url https://bucket.{エンドポイントのURL} cp s3://{バケット名}/test2.txt aws s3 --endpoint-url https://bucket.vpce-0700000000000-1234567.s3.ap-northeast-1.vpce.amazonaws.com cp test.txt s3://sujae-peering-test-1/test2.txt
バケットでtest2.txt を確認できたら成功です。
他に設定できること
エンドポイントの詳細は 公式 ドキュメントを参照してください。
まず、バケットへの通信だけできるようにエンドポイントのポリシーを設定することができます。
{ "Version": "2012-10-17", "Id": "Policy1415115909151", "Statement": [ { "Sid": "Access-to-specific-bucket-only", "Principal": "*", "Action": [ "s3:GetObject", "s3:PutObject" ], "Effect": "Allow", "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET1", "arn:aws:s3:::DOC-EXAMPLE-BUCKET1/*"] } ] }
また、S3 のポリシーにもエンドポイントからの接続だけを許可することもできます。
{ "Version": "2012-10-17", "Id": "Policy1415115909152", "Statement": [ { "Sid": "Access-to-specific-VPCE-only", "Principal": "*", "Action": "s3:*", "Effect": "Deny", "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET2", "arn:aws:s3:::DOC-EXAMPLE-BUCKET2/*"], "Condition": {"StringNotEquals": {"aws:sourceVpce": "vpce-1a2b3c4d"}} } ] }
上記設定の詳細な説明は 公式 ドキュメントを参照してください。
まとめ
こうしてVPC peering を利用してパブリックインターネットを通じないS3 アップロード方法を見てみました。
インターフェイスエンドポイント(privatelink)はS3 へのアップロードだけではなくさまざまなサービスと連携して使うことが多いので、調べてみることをお勧めします。
お読みいただきありがとうございます。
誤字脱字、内容フィードバックはいつもありがとうございます。must01940 gmailでお願いします。